home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / AppleScript / Additions / Wild 1.0.1 / project / C sources / match.c next >
Encoding:
Text File  |  1994-05-09  |  10.9 KB  |  353 lines  |  [TEXT/KAHL]

  1. //    match.c        matching functions for the wildcard AppleScript extension
  2. //
  3. //    93/11/19    File created
  4. //    94/01/24    *** released Wild 1.0.0 ***
  5. //    94/05/09    Totally removed the licensing mechanism and added the GNU comments
  6. //
  7. //--------------------------------------------------------------------------------------------------
  8. //  Copyright © 1993, 1994 by Rainbow Hill Pty Ltd.
  9. //
  10. //    This program is free software; you can redistribute it and/or modify it under the terms of
  11. //    the GNU General Public License as published by the Free Software Foundation; either version 2
  12. //    of the License, or any later version.
  13. //
  14. //    This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  15. //    without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  16. //    See the GNU General Public License for more details.
  17. //
  18. //    You should have received a copy of the GNU General Public License along with this program;
  19. //    if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. //
  21.  
  22. #include <Errors.h>
  23. #include <string.h>
  24. #include "wild.h"
  25. #include "match.h"
  26.  
  27. static Boolean matchStr(
  28.                 char *,                // --> trailing part of filename to be checked
  29.                 char *,                // --> fixed string to be found
  30.                 match_wild_t *,        // --> list of wildcards
  31.                 short,                // --> number of wildcards
  32.                 short                // --> current wildcard (i.e. the wildcard to be checked here)
  33.                 );
  34.  
  35. //************************************************************************************ match_criteria
  36. Boolean match_criteria(
  37.                         CInfoPBRec    *param,        // --> Cat Info Param block of the item
  38.                         wild_parm_t    *parms        // --> flags and wildcarded strings
  39.                         ) {
  40.     Boolean result;
  41.  
  42.     result = false;
  43.  
  44.     // find out whether it is a file or a folder
  45.     if ((param->dirInfo.ioFlAttrib & ioDirMask) == 0) {
  46.  
  47.         // it is a file
  48.         if (parms->files == false) goto RET_LBL;                                        // --->
  49.  
  50.         // check the creator if necessary
  51.         if (
  52.                 parms->doCreator == true
  53.                 &&
  54.                 match_OSType(
  55.                                         param->hFileInfo.ioFlFndrInfo.fdCreator,
  56.                                         parms->creator,
  57.                                         parms->doShort,
  58.                                         parms->shortW
  59.                                 ) == false
  60.             ) goto RET_LBL;                                                                // --->
  61.  
  62.         // check the file type if necessary
  63.         if (
  64.                 parms->doType == true
  65.                 &&
  66.                 match_OSType(
  67.                                         param->hFileInfo.ioFlFndrInfo.fdType,
  68.                                         parms->type,
  69.                                         parms->doShort,
  70.                                         parms->shortW
  71.                                 ) == false
  72.             ) goto RET_LBL;                                                                // --->
  73.         }
  74.     else {
  75.  
  76.         // it is a folder
  77.         if (parms->folders == false) goto RET_LBL;                                        // --->
  78.         }            
  79.  
  80.     // if we arrive here, the item has passed all the checks
  81.     result = true;
  82.  
  83. RET_LBL:
  84.  
  85.     return (result);
  86.     } // match_criteria
  87.  
  88. //************************************************************************************ match_OSType
  89. Boolean match_OSType(
  90.                     OSType            what,        // --> OSType to be matched
  91.                     OSType            this,        // --> with this
  92.                     Boolean            doWild,        // --> do wildcarding
  93.                     char            wildcard    // --> wildcard character
  94.                     ) {
  95.     Boolean        result;
  96.     short        k;
  97.     char        *whatP;
  98.     char        *thisP;
  99.  
  100.     if (doWild == false) {
  101.         result = (what == this) ? true : false;
  102.         }
  103.     else {
  104.         whatP = (char *)&what;
  105.         thisP = (char *)&this;
  106.         result = true;
  107.         for (k = 0; k < 4 && result == true; k++) {
  108.             if (whatP[k] != thisP[k]  &&  thisP[k] != wildcard) result = false;
  109.             }
  110.         }
  111.  
  112.     return (result);
  113.     } // match_OSType
  114.  
  115. //************************************************************************************ match_setWild
  116. short match_setWild(
  117.                     char            *what,        // <-> wildcarded filename
  118.                     wild_parm_t        *parms,        // --> flags and wildcarded strings
  119.                     match_wild_t    *wilds        // <-- list of wildcards
  120.                     ) {
  121.     short        n;
  122.     short        k;
  123.     short        nWild;            // returned value
  124.     char        wildChars[3];
  125.     Boolean        isWild;
  126.  
  127.     isWild = false;
  128.     nWild = 0;
  129.  
  130.     // if the filtering is not case sensitive, convert the name to upper case
  131.     if (parms->caseS == false) {
  132.         c2pstr(what);
  133.         UprString((unsigned char *)what, true);
  134.         p2cstr(what);
  135.         }
  136.  
  137.     // determine whether wildcarding is enabled and there are wildcards
  138.     k = 0;
  139.     if (parms->doLong == true  &&  strchr(what, (int)parms->longW) != NULL) {
  140.         wildChars[k++] = parms->longW;
  141.         isWild = true;
  142.         }
  143.     if (parms->doShort == true  &&  strchr(what, (int)parms->shortW) != NULL) {
  144.         wildChars[k++] = parms->shortW;
  145.         isWild = true;
  146.         }
  147.  
  148.     // if wildcarding is enabled and there are wildcards in the name, scan the name
  149.     // and fill in the wildcarding structure
  150.     if (isWild) {
  151.  
  152.         // first of all terminate the string which contains all wildcard characters
  153.         wildChars[k] = '\0';
  154.  
  155.         //
  156.         // In the following loop, the variable 'n' is used to index the next
  157.         // character of the string which needs to be checked. Therefore, when
  158.         // 'n' coincides with the length of the string, the whole string has
  159.         // been checked.
  160.         // 'k' is used to temporarily store the distance between the current
  161.         // position and the position of the next wildcard.
  162.         //
  163.         n = 0;
  164.         do {
  165.             k = strcspn(&what[n], (const char *)wildChars);
  166.             if (parms->doShort == true  &&  what[n + k] == parms->shortW) {
  167.                 if (k == 0 && nWild > 0) {    // just following another wildcard ?
  168.                     wilds[nWild - 1].size++;
  169.                     wilds[nWild - 1].min++;
  170.                     wilds[nWild - 1].max++;
  171.                     }
  172.                 else {
  173.                     wilds[nWild].offset = k;
  174.                     wilds[nWild].size = 1;
  175.                     wilds[nWild].min = 1;
  176.                     wilds[nWild].max = 1;
  177.                     nWild++;
  178.                     }
  179.                 }
  180.             else if (parms->doLong == true  &&  what[n + k] == parms->longW) {
  181.                 if (k == 0 && nWild > 0) {    // just following another wildcard ?
  182.                     wilds[nWild - 1].size++;
  183.                     wilds[nWild - 1].max = WILD_maxFilenameLen;
  184.                     }
  185.                 else {
  186.                     wilds[nWild].offset = k;
  187.                     wilds[nWild].size = 1;
  188.                     wilds[nWild].min = 0;
  189.                     wilds[nWild].max = WILD_maxFilenameLen;
  190.                     nWild++;
  191.                     }
  192.                 }
  193.             n += k + 1;
  194.             } while (n < strlen((const char *)what));
  195.         } // we had to process wildcards
  196.  
  197.     return (nWild);
  198.     } // match_setWild
  199.  
  200. //************************************************************************************ match_string
  201. Boolean match_string(
  202.                     char            *name,        // --> string to be matched
  203.                     char            *f,            // --> wildcarded filename
  204.                     match_wild_t    *wilds,        // --> list of wildcards
  205.                     short            nWild,        // --> number of wildcards
  206.                     Boolean            caseSens    // --> true: case sensitive
  207.                     ) {
  208.     Boolean            success;
  209.     short            firstOffset;
  210.     char            ff[WILD_maxFilenameLen + 1];    // copy of the wildcarded filename
  211.     short            k;
  212.     char            *aPtr;
  213.     char            *x;
  214.     char            upName[WILD_nameLength];
  215.  
  216.  
  217.     // if the filtering is not case sensitive, convert the name to upper case
  218.     if (caseSens == false) {
  219.         strcpy(upName, (const char *)name);
  220.         c2pstr(upName);
  221.         UprString((unsigned char *)upName, true);
  222.         p2cstr(upName);
  223.         x = upName;
  224.         }
  225.     else {
  226.         x = name;
  227.         }
  228.  
  229.     // handle the case when there are no wildcards at all
  230.     if (nWild == 0) {
  231.         if (strcmp((const char *)x, (const char *)f) == 0) {
  232.             success = true;
  233.             }
  234.         else {
  235.             success = false;
  236.             }
  237.         goto RETURN_LBL;                                                                    // --->
  238.         }
  239.  
  240.     // check whether there is a string before the first wildcard and whether it matches
  241.     firstOffset = wilds[0].offset;
  242.     if (firstOffset > 0 && strncmp((const char *)x, (const char *)f, firstOffset) != 0) {
  243.         success = false;
  244.         goto RETURN_LBL;                                                                    // --->
  245.         }
  246.  
  247.     // Mask the first character of each wildcarded section with a null, so that searches can
  248.     // be done easily. Note that we do not need to mask the first wildcard because we will not
  249.     // search the filename looking for the leading string.
  250.     strcpy(ff, (const char *)&f[firstOffset]);
  251.     aPtr = ff;
  252.     for (k = 1; k < nWild; k++) {
  253.         aPtr = &aPtr[wilds[k].offset + wilds[k - 1].size];
  254.         *aPtr = '\0';
  255.         }
  256.  
  257.     // now we can start matching from the first wildcard
  258.     success = matchStr(&x[firstOffset], &ff[wilds[0].size], wilds, nWild, 0);
  259.  
  260. RETURN_LBL:
  261.     return (success);
  262.     } // match_string
  263.  
  264. //------------------------------------------------------------------------------------ matchStr
  265. static Boolean matchStr(
  266.         char            *x,            // --> trailing part of filename to be checked
  267.         char            *f,            // --> fixed string to be found
  268.         match_wild_t    *wilds,        // --> list of wildcards
  269.         short            nWild,        // --> number of wildcards
  270.         short            kWild        // --> current wildcard (i.e. the wildcard to be checked here)
  271.         ) {
  272.     Boolean        success;
  273.     char        *theStr;    // pointer to the fixed string found in the filename
  274.     char        *xx;        // pointer to part of 'x' to be searched for 'f'
  275.     short        len;        // length of the filename part matched by the current wildcard
  276.     short        nextW;        // next wildcard number (if any)
  277.     short        fLen;        // length of the current fixed string
  278.     char        *nextX;        // what is left to the filename to be matched by further wildcards
  279.     char        *nextF;        // next wildcard and fixed string
  280.  
  281.     success = false;
  282.  
  283.     if (*f == '\0') {
  284.         //
  285.         // There is no fixed string. As contiguous wildcard characters are grouped into
  286.         // wildcarding sections, the absence of a fixed string means that the wildcarded
  287.         // filename terminates with a wildcard and that we are now processing precisely the
  288.         // last wildcarding section. This implies that we have to match the whole 'xx'. The
  289.         // only condition which needs to be satisfied is that the length of 'xx' is within
  290.         // the 'min' and 'max' of the current wildcarding section.
  291.         //
  292.         len = strlen((const char *)x);
  293.         if (len >= wilds[kWild].min && len <= wilds[kWild].max) success = true;
  294.         goto RETURN_LBL;                                                                    // --->
  295.         }
  296.  
  297.     // Well, there is a fixed string. Let's prepare to scan what is left of the filename.
  298.     xx = x;
  299.     nextW = kWild + 1;
  300.     fLen = strlen((const char *)f);
  301.  
  302.     // When we enter this function there is always at least one wildcard.
  303.     // Let's search the filename to find the fixed string.
  304.     do {
  305.         theStr = strstr((const char *)xx, (const char *)f);
  306.         if (theStr == NULL) goto RETURN_LBL;                                                // --->
  307.  
  308.         // The matching string has been found. Calculate the length of the filename part
  309.         // which matches the current wildcard.
  310.         len = (short)(theStr - x);
  311.         if (len > wilds[kWild].max) goto RETURN_LBL;                                        // --->
  312.         if (len < wilds[kWild].min) {
  313.  
  314.             // Match too short. Keep trying.
  315.             xx++;
  316.  
  317.             }
  318.         else {
  319.  
  320.             // String found and the match has an acceptable length. Check the rest.
  321.             nextX = theStr + fLen;
  322.  
  323.             // check whether there are further wildcards and prepare to search on
  324.             if (nextW < nWild) {
  325.  
  326.                 // there are further wildcards (wilds.size includes the null which terminates 'f')
  327.                 nextF = f + (wilds[nextW].size + fLen);
  328.  
  329.                 // call 'matchStr' recursively
  330.                 success = matchStr(nextX, nextF, wilds, nWild, nextW);
  331.  
  332.                 // Prepare a new attempt to match the current wildcard. This will only be
  333.                 // necessary if 'success' is false, but let's not waste time to check it.
  334.                 xx++;
  335.  
  336.                 } // there were further wildcards past the current one
  337.             else {
  338.  
  339.                 // There are no further wildcards. Check that we have no trailing characters
  340.                 // left and, if there are, try a new match before giving up.
  341.                 if (*nextX == '\0')
  342.                     success = true;
  343.                 else
  344.                     xx++;
  345.                 } // we have just processed the last wildcard
  346.             } // the match was not too short
  347.  
  348.         } while (success == false);
  349.  
  350. RETURN_LBL:
  351.     return (success);
  352.     } // matchStr
  353.